package com.yuntsg.ruiijn.database_genrepository.service;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest;
import co.elastic.clients.elasticsearch.core.DeleteByQueryResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yuntsg.nnsfcp.common.utils.UserUtil;
import com.yuntsg.ruiijn.database_genrepository.entity.FileDetailsGenrepository;
import com.yuntsg.ruiijn.database_genrepository.entity.FileRecordGenrepository;
import com.yuntsg.ruiijn.database_genrepository.entity.InitConfig;
import com.yuntsg.ruiijn.database_genrepository.mapper.FileDetailGenrepositoryMapper;
import com.yuntsg.ruiijn.databse_search.BaseService;
import com.yuntsg.ruiijn.databse_search.service.FeatureService;
import common.bean.CoordinateVo;
import common.bean.PubSearchRequestVo;
import common.bean.R;
import common.util.MinioUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat;
import org.opencv.core.Rect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

@Service
@Slf4j
@DS("master")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class FileDetailsGenrepositoryService extends BaseService<FileDetailGenrepositoryMapper, FileDetailsGenrepository> {


    private static final String IMAGE_INDEX = "picture_vector_prod";
    private final MinioUtil minioUtil;
    private final ElasticsearchClient esClient;
    private final FeatureService featureService;
    private final FileRecordGenrepositoryService fileRecordInteriorService;

    @Resource
    UserUtil userUtil;

    /**
     * 图片手动切割
     *
     * @return
     * @throws IOException
     */
    public R pictureManually(@RequestBody PubSearchRequestVo requestVo) {
        String originalId = requestVo.getOriginalId();
        FileDetailsGenrepository fileDetails = this.getById(originalId);

        if (null != requestVo.getCoordinateList() && requestVo.getCoordinateList().size() > 0) {

            for (CoordinateVo coordinateVo : requestVo.getCoordinateList()) {
                Integer xTop = coordinateVo.getTopx();
                Integer yTop = coordinateVo.getTopy();
                Integer xBottom = coordinateVo.getBottomx();
                Integer yBottom = coordinateVo.getBottomy();
                String[] split = fileDetails.getPath().split("/");
                // 保存图片

                String path = fileDetails.getPath().replace(split[split.length - 1], "");
                Mat croppedImage = null;
                try {
                    if (!FileUtil.exist(InitConfig.tempImgPath + path)) {
                        FileUtil.mkdir(InitConfig.tempImgPath + path);
                    }
                    path += RandomUtil.randomString(6) + ".jpg";

                    Mat src = minioUtil.downloadMat(fileDetails.getPath());
                    croppedImage = new Mat(src, new Rect(xTop, yTop, (xBottom - xTop), (yBottom - yTop)));
                } catch (Exception e) {
                    return R.error("图片切割失败,请选择区域重试");
                }

                String docx = minioUtil.upload(minioUtil.coverInput(croppedImage), path, userUtil.getUidStr());

                FileDetailsGenrepository fileDetailsS = new FileDetailsGenrepository();

                fileDetailsS.setFId(fileDetails.getId());
                fileDetailsS.setTpye(6);
                fileDetailsS.setRid(Optional.ofNullable(fileDetails.getRid()).orElse(fileDetailsS.getFId()));
//                fileDetailsS.setCollectionStatus(source);
//                fileDetailsS.setSplitStatus(0);
                fileDetailsS.setCollectionStatus(fileDetails.getCollectionStatus());

                fileDetailsS.setStatus(0);
                fileDetailsS.setPath(docx);
                fileDetailsS.setTopX(xTop);
                fileDetailsS.setTopY(yTop);
                fileDetailsS.setBottomX(xBottom);
                fileDetailsS.setBottomY(yBottom);


                this.saveOrUpdate(fileDetailsS);

            }

        } else {
            return R.error("请选择区域");
        }
        return R.ok();
    }


    public List<FileDetailsGenrepository> picList(Integer rid, Integer fid, Integer type) {
        return this.list(Wrappers.<FileDetailsGenrepository>lambdaQuery().eq(FileDetailsGenrepository::getRid, rid)
                .eq(FileDetailsGenrepository::getTpye, type)
                .eq(FileDetailsGenrepository::getFId, fid)
                .eq(FileDetailsGenrepository::getDeleteFlag, 0));
    }

    /**
     * 同步操作
     *
     * @param ids
     */
    public void putPendingList(String[] ids) {
        Integer rid = this.getById(ids[0]).getRid();
        FileRecordGenrepository record = fileRecordInteriorService.getById(rid);
        String pmut = record.getPmut();
        if (StrUtil.isNotEmpty(pmut)) {
            deleteWithFiled(pmut);
        }

        List<FileDetailsGenrepository> list = this.list(Wrappers.<FileDetailsGenrepository>lambdaQuery().in(FileDetailsGenrepository::getId, ids));
        if (list.size() > 0) {

            List<BulkOperation> eslist = new ArrayList<>();
            for (FileDetailsGenrepository f : list) {
                FileDetailsGenrepository fdetail = this.getById(f.getFId());
                Map<String, Object> doc = new HashMap<>();

                String termFiled = "";
                if (record.getPmut().startsWith("TU")) {
                    termFiled = "ut";
                } else if (NumberUtil.isNumber(record.getPmut())) {
                    termFiled = "pm";
                } else {
                    termFiled = "doi";
                }

                doc.put("id", f.getId());
                doc.put(termFiled, record.getPmut());
                doc.put("rid", record.getId());
                doc.put("table_no", fdetail.getTableNo());
                doc.put("serial_id", fdetail.getSerialId());
                doc.put("year", 9999);
                doc.put("top_x", f.getTopX());
                doc.put("top_y", f.getTopY());
                doc.put("bottom_x", f.getBottomX());
                doc.put("bottom_y", f.getBottomY());
                doc.put("type", 1);
                doc.put("img_name", StrUtil.subAfter(f.getPath(), "/", true));
                doc.put("vector", featureService.imageFeature(f.getPath()));
                this.saveOrUpdate(f.setSyncStatus(2).setSyncTime(System.currentTimeMillis()).setSyncId(userUtil.getUidStr()));
                eslist.add(new BulkOperation.Builder().create(builder -> builder.id(f.getId().toString()).index(IMAGE_INDEX).document(doc)).build());
            }
            try {
                BulkResponse response = esClient.bulk(builder -> builder.index(IMAGE_INDEX).operations(eslist));
            } catch (Exception e) {
                log.error("插入失败:{}", e.getMessage());
            }
            fileRecordInteriorService.update(Wrappers.<FileRecordGenrepository>lambdaUpdate().eq(FileRecordGenrepository::getId, rid).set(FileRecordGenrepository::getSyncStatus, 1).set(FileRecordGenrepository::getSyncId, userUtil.getUidStr()).set(FileRecordGenrepository::getSyncTime, System.currentTimeMillis()));

        }

    }

    public List<FileDetailsGenrepository> pendinglist(Integer rid, Integer type) {
        return this.list(Wrappers.<FileDetailsGenrepository>lambdaQuery().eq(FileDetailsGenrepository::getSyncStatus, type).eq(FileDetailsGenrepository::getRid, rid));
    }

    public void delete(String[] ids) {
        for (String id : ids) {
            try {
                esClient.delete(builder -> builder.index(IMAGE_INDEX).id(id));
                this.update(Wrappers.<FileDetailsGenrepository>lambdaUpdate().eq(FileDetailsGenrepository::getId, id).set(FileDetailsGenrepository::getSyncStatus, 0).set(FileDetailsGenrepository::getSyncTime, null).set(FileDetailsGenrepository::getSyncId, null));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void deleteWithFiled(String value) {
        String termFiled = "";
        if (value.startsWith("UT")) {
            termFiled = "ut";
        } else if (NumberUtil.isNumber(value)) {
            termFiled = "pm";
        } else {
            termFiled = "doi";
        }

        String finalTermFiled = termFiled;
        Query of = Query.of(q -> q.bool(b -> b
                .mustNot(Query.of(c -> c.term(s -> s.field("table_no").value(8889))))
                .must(Query.of(c -> c.term(s -> s.field(finalTermFiled).value(value)))))).bool()._toQuery();
        DeleteByQueryRequest delete = DeleteByQueryRequest.of(builder -> builder
                .index(IMAGE_INDEX)
                .query(of));
        try {
            DeleteByQueryResponse deleteByQueryResponse = esClient.deleteByQuery(delete);
            if (deleteByQueryResponse.deleted() > 0) {
                log.info("删除文档成功," + deleteByQueryResponse.deleted());
            }
        } catch (IOException e) {
            log.info("删除文档异常");
        }


    }

}
